package com.biz.ssm.controller.base;

import com.alibaba.fastjson.JSON;
import com.biz.ssm.base.Response;
import com.biz.ssm.enums.CodeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

@ControllerAdvice
@RestController
public class ErrorController extends BasicErrorController {

	private static Logger logger = LoggerFactory.getLogger(ErrorController.class);

	public static final String DEFAULT_ERROR_VIEW = "error";

	public ErrorController(ServerProperties serverProperties) {
		super(new DefaultErrorAttributes(), serverProperties.getError());
	}

	@Override
	public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
		Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
		HttpStatus status = getStatus(request);
		return new ResponseEntity<Map<String, Object>>(body, status);
	}

	/**
	 * 覆盖默认的HTML响应
	 */
	@Override
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
		// 请求的状态
		HttpStatus status = getStatus(request);
		String message = "["+status.value()+"]请求出错了~";
		Response<Object> resp = Response.resp(CodeEnum.FAILED.getCode(),message,null);
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		PrintWriter out = null;
		try {
			out = response.getWriter();
			out.append(JSON.toJSONString(resp));
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.close();
			}
		}
		return null;
	}

	@ExceptionHandler({IllegalArgumentException.class })
    public Response<Object> handleException(HttpServletRequest req, HttpServletResponse resp, IllegalArgumentException e) {
        return Response.resp(CodeEnum.FAILED.getCode(),e.getMessage(),null);
    }

	@ExceptionHandler({Exception.class })
    public Response<Object> handleException(HttpServletRequest req,HttpServletResponse resp,Exception e) {
		logger.error(e.getMessage() , e);
        return Response.resp(CodeEnum.FAILED.getCode(),e.getMessage(),null);
    }

	@ExceptionHandler({MethodArgumentNotValidException.class })
    public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest req,HttpServletResponse resp,MethodArgumentNotValidException e) {
		List<ObjectError> errors = e.getBindingResult().getAllErrors();
		StringBuilder errorMsg = new StringBuilder();
		errors.forEach(x->errorMsg.append(x.getDefaultMessage()).append(";"));
		return Response.resp(CodeEnum.FAILED.getCode(),errorMsg.toString(),null);
    }

	@ExceptionHandler({AccessDeniedException.class })
	public Response<Object> handleMethodArgumentNotValidException(HttpServletRequest req,HttpServletResponse resp,AccessDeniedException e) {
		return Response.resp(CodeEnum.NOT_LOGIN.getCode(),CodeEnum.NOT_LOGIN.getMessage(),null);

	}

}
